﻿using System;
using System.IO;
using log4net;
using PortableVersion.Core.FileSystem.Services;
using PortableVersion.Core.SourceControl.CommandLine;

namespace PortableVersion.Core.SourceControl
{
    public class SourceControlCmdService : ISourceControlService
    {
        private readonly ILog _log;
        private readonly SourceControlConfiguration _config;
        private string _root;

        public void CheckOut(string path)
        {
            _log.InfoFormat(@"Checking out '{0}'", path);
            var param = _config.GetCommand(SourceControlActions.CheckOut,
                                             SourceControlCommandLineHelper.GetParam(SourceControlParam.Name, Relative(path)));
            ExecuteCommand(param);
        }

        private string Relative(string path)
        {
            if (Path.IsPathRooted(path))
            {
                return path.Substring(_root.Length).TrimStart(@"\/".ToCharArray());
            }
            throw new ArgumentException(@"Must be an absolute path.", "path");
        }

        private void ExecuteCommand(string param)
        {
            _log.InfoFormat(@"Executing: {0} {1}", _config.Command, param);
            if (SourceControlCommandLineHelper.Execute(_root, _config.Command, param))
            {
                _log.Info(@"Operation succeeded");
                return;
            }
            _log.ErrorFormat(@"Execution of the source control command with parameter '{0}' filed.", param);
            throw new SourceControlException("Executing source control command with parameters '{0}' did not succeed!", 
                _config.Command + " " + param);
        }

        public void SetRoot(string root)
        {
            _root = root;
            _log.InfoFormat(@"TfsService's root path is set to '{0}'", root);
        }

        public void Add(string path)
        {
            _log.InfoFormat(@"Adding '{0}' to the source control.", path);
            var param = _config.GetCommand(SourceControlActions.Add,
                                             SourceControlCommandLineHelper.GetParam(SourceControlParam.Name, Relative(path)));
            ExecuteCommand(param);
        }

        public void Rename(string path, string newPath)
        {
            _log.InfoFormat(@"Renaming or moving '{0}' to '{1}' from TFS.", path, newPath);
            var param = _config.GetCommand(SourceControlActions.Rename,
                                             SourceControlCommandLineHelper.GetParam(SourceControlParam.Name, Relative(path),
                                             SourceControlParam.NewName, Relative(newPath)
                                             ));
            ExecuteCommand(param);
        }

        public void Delete(string path)
        {
            _log.InfoFormat(@"Deleting '{0}' from TFS.", path);
            try
            {
                var param = _config.GetCommand(SourceControlActions.Delete,
                                                 SourceControlCommandLineHelper.GetParam(SourceControlParam.Name, Relative(path)));
                ExecuteCommand(param);
            }
            catch (SourceControlException)
            {
                //try undo if delete is not working
                var param = _config.GetCommand(SourceControlActions.Undo,
                                                 SourceControlCommandLineHelper.GetParam(SourceControlParam.Name, Relative(path)));
                ExecuteCommand(param);
            }
        }

        public void AddFolder(string addedItem)
        {
            _log.Info(@"AddFolder not supported.");
        }

        public void RenameFolder(string path, string newName)
        {
            _log.Info(@"Rename folder not supported.");
        }

        public void DeleteFolder(string path)
        {
            Delete(path);
        }

        public SourceControlCmdService(ILog log, string sourceControlConfigFile)
        {
            _log = log;
            _config = SourceControlConfiguration.Load(sourceControlConfigFile);
        }
    }
}
